package com.lzb.interceptor;

import java.util.List;

import javax.annotation.Resource;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.lzb.common.constant.CommonConstantValues;
import com.lzb.common.constant.favourite.ConstantValues;
import com.lzb.common.helper.redis.RedisHelper;
import com.lzb.domain.MngMoment;

/**
 * @author lizebin
 *
 * 这里有两个问题需要注意：
 * 	a.“雪崩”现象：就是说如果缓存失效，所有的查询压力就会转移到数据库
 *  b.缓存穿透问题：查询一个一定不存在的数据，由于缓存不命中，并且出于容错考虑，如果从数据库查不到数据，则不写到缓存，这将导致这个不存在的查询，每次都会“穿过”缓冲层去查数据库
 *  http://carlosfu.iteye.com/blog/2248185
 *  此处采用存储空值的方案：
 *  
 */
@Component(MngMomentServiceCacheInterceptor.BEAN_PACKAGE_NAME)
@Aspect
public class MngMomentServiceCacheInterceptor implements Ordered {
	public static final String BEAN_PACKAGE_NAME = "com.lzb.interceptor.MngMomentServiceCacheInterceptor";
	
	@Resource(name = RedisHelper.BEAN_PACKAGE_NAME)
	private RedisHelper redisHelper;
	/**
	 * 添加、删除朋友圈后置通知
	 */
	private final String MNG_MOMENT_ADD_AFTER_POINTCUT_EXECUTION = "execution(* com.lzb..MngMomentService.add*(..)) || execution(* com.lzb..MngMomentService.batchAdd*(..)) ";
	private final String MNG_MOMENT_DELETE_AFTER_POINTCUT_EXECUTION = "execution(* com.lzb..MngMomentService.del*(..))";

	public MngMomentServiceCacheInterceptor() {}

	@AfterReturning(MNG_MOMENT_ADD_AFTER_POINTCUT_EXECUTION)
	public void mngMomentAddAfterPointcutExecution(JoinPoint pjp) {
		Object[] args = pjp.getArgs();
		if(args[0] instanceof List<?>) {
			List<?> mngMomentLst = (List<?>) args[0];
			for(Object _m : mngMomentLst) {
				MngMoment m = (MngMoment)_m;
				redisHelper.set(ConstantValues.DOMAIN_MOMENT + CommonConstantValues.REDIS_SPLITTER + m.getUuid(), JSON.toJSONString(m));
			}
		} else if(args[0] instanceof MngMoment) {
			MngMoment m = (MngMoment) args[0];
			redisHelper.set(ConstantValues.DOMAIN_MOMENT + CommonConstantValues.REDIS_SPLITTER + m.getUuid(), JSON.toJSONString(m));
		}
	}
	
	@AfterReturning(MNG_MOMENT_DELETE_AFTER_POINTCUT_EXECUTION)
	public void mngMomentDelAfterPointcutExecution(JoinPoint pjp) {
		Object[] args = pjp.getArgs();
		if(args[0] instanceof String[]) {
			for(String momentUUID : (String[])args[0]) {
				redisHelper.del(ConstantValues.DOMAIN_MOMENT + CommonConstantValues.REDIS_SPLITTER + momentUUID);
			}
		}
	}

	@Override
	public int getOrder() {
		return 1;
	}
}
